package com.dc.web.controller;


import com.dc.constant.MessageConstant;
import com.dc.dao.*;
import com.dc.entity.*;
import com.dc.exception.ServiceException;
import com.dc.model.AjaxResult;
import com.dc.model.WorkflowListBody;
import com.dc.model.WorkflowPowerBody;
import com.dc.service.CalibrationService;
import com.dc.service.HttpService2;
import com.dc.service.dto.CalibrationShipCutDto;
import com.dc.service.dto.electronic.HttpGetPowerReturnNewBody;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.Email;
import java.util.*;

@Api(tags = "0-单船工序-船体下料")
@RequestMapping("/api/workflow_ship_cut")
@RestController
public class WorkflowShipCutController {

    @Resource
    WorkflowShipCutDao workflowShipCutDao;

    @Resource
    WorkflowShipCutChildDao workflowShipCutChildDao;

    @Resource
    ShipRepairDao shipRepairDao;

    @Resource
    ShipDao shipDao;

    @Resource
    CalibrationService calibrationService;

    @Resource
    HttpService2 httpService2;

    @GetMapping("/list")
    public AjaxResult list(WorkflowListBody body) {

        Integer pageNumber = body.getPageNumber();
        pageNumber = ObjectUtils.defaultIfNull(pageNumber, 1);
        Integer pageSize = body.getPageSize();
        pageSize = ObjectUtils.defaultIfNull(pageSize, 20);

        PageRequest pageRequest = PageRequest.of(pageNumber - 1, pageSize);

        Long repairId = body.getRepairId();     // 维修工单id

        Optional<ShipRepairEntity> optionalShipRepair = shipRepairDao.findById(repairId);
        if(!optionalShipRepair.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_SHIP_REPAIR_MISSING);
        }

        ShipRepairEntity shipRepairEntity = optionalShipRepair.get();

        Long shipId = shipRepairEntity.getShipId();
        Optional<ShipEntity> optionalShip = shipDao.findById(shipId);
        if(!optionalShip.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_SHIP_MISSING);
        }

        ShipEntity shipEntity = optionalShip.get();

        Page<WorkflowShipCutEntity> resultList = workflowShipCutDao.findByShipRepairEntity(shipRepairEntity, pageRequest);

        CalibrationShipCutDto calibrationShipCutDto = calibrationService.calcShipCut();

        resultList.getContent().forEach(t -> {
            dynamicCalc(t, shipEntity, shipRepairEntity, calibrationShipCutDto);
        });

        return AjaxResult.success(resultList);
    }

    @GetMapping("/{id}")
    public AjaxResult show(@PathVariable("id") Long id) {

        Optional<WorkflowShipCutEntity> optional = workflowShipCutDao.findById(id);
        if(!optional.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_WORK_FLOW_MISSING);
        }

        WorkflowShipCutEntity shipOilEntity = optional.get();

        ShipRepairEntity shipRepairEntity = shipOilEntity.getShipRepairEntity();

        Long shipId = shipRepairEntity.getShipId();
        Optional<ShipEntity> optionalShip = shipDao.findById(shipId);

        if(!optionalShip.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_SHIP_MISSING);
        }

        ShipEntity shipEntity = optionalShip.get();

        CalibrationShipCutDto calibrationShipCutDto = calibrationService.calcShipCut();

        dynamicCalc(shipOilEntity, shipEntity, shipRepairEntity, calibrationShipCutDto);

        return AjaxResult.success(shipOilEntity);
    }


    //  shipRepairId   weight   shipWeight    submit_time
    @PostMapping()
    public AjaxResult add(@RequestBody WorkflowShipCutEntity entity) {

        entity.setId(null);

        Long shipRepairId = entity.getShipRepairId();
        Optional<ShipRepairEntity> optionalShipRepair = shipRepairDao.findById(shipRepairId);
        if(!optionalShipRepair.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_SHIP_REPAIR_MISSING);
        }

        ShipRepairEntity shipRepairEntity = optionalShipRepair.get();

        Long shipId = shipRepairEntity.getShipId();
        Optional<ShipEntity> optionalShip = shipDao.findById(shipId);
        if(!optionalShip.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_SHIP_MISSING);
        }

        ShipEntity shipEntity = optionalShip.get();

        entity.setShipRepairEntity(shipRepairEntity);
        entity.setSubmitTime(new Date());

        WorkflowShipCutEntity save = workflowShipCutDao.save(entity);

        //todo
        CalibrationShipCutDto calibrationShipCutDto = calibrationService.calcShipCut();

        dynamicCalc(save, shipEntity, shipRepairEntity, calibrationShipCutDto);

        return AjaxResult.success(save);
    }

    @PutMapping("/{id}")
    public AjaxResult update(@PathVariable("id") Long id, @RequestBody WorkflowShipCutEntity entity) {

        Optional<WorkflowShipCutEntity> optionalPaintHouse = workflowShipCutDao.findById(id);
        if(!optionalPaintHouse.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_WORK_FLOW_MISSING);
        }

        WorkflowShipCutEntity houseEntity = optionalPaintHouse.get();

        ShipRepairEntity shipRepairEntity = houseEntity.getShipRepairEntity();

        Long shipId = shipRepairEntity.getShipId();
        Optional<ShipEntity> optionalShip = shipDao.findById(shipId);
        if(!optionalShip.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_SHIP_MISSING);
        }

        ShipEntity shipEntity = optionalShip.get();

        //////////////////////// 设置字段
        houseEntity.setWeight(entity.getWeight());
        houseEntity.setShipWeight(entity.getShipWeight());
        houseEntity.setRoom(entity.getRoom());
        houseEntity.setSubmitTime(new Date());

        WorkflowShipCutEntity save = workflowShipCutDao.save(houseEntity);

        CalibrationShipCutDto calibrationShipCutDto = calibrationService.calcShipCut();

        dynamicCalc(save, shipEntity, shipRepairEntity, calibrationShipCutDto);

        return AjaxResult.success(save);
    }

    @DeleteMapping("/{id}")
    public AjaxResult delete(@PathVariable("id") Long id) {

        workflowShipCutDao.deleteById(id);

        return AjaxResult.success();
    }

    /////////////////////////////////////////////////// child
    @GetMapping("/child/{id}")
    public AjaxResult showChild(@PathVariable("id") Long id) {
        Optional<WorkflowShipCutChildEntity> optional = workflowShipCutChildDao.findById(id);
        if(!optional.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_WORK_FLOW_MISSING);
        }

        WorkflowShipCutChildEntity houseChildEntity = optional.get();

        houseChildEntity.setPid(houseChildEntity.getWorkflowShipCutEntity().getId());

        return AjaxResult.success(houseChildEntity);
    }

    @PostMapping("/child")
    public AjaxResult addChild(@RequestBody WorkflowShipCutChildEntity entity) {

        entity.setId(null); // 新增保证 id = null，避免变成更新

        Optional<WorkflowShipCutEntity> optionalPainHouse = workflowShipCutDao.findById(entity.getPid());
        if(!optionalPainHouse.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_WORK_FLOW_MISSING);
        }

        WorkflowShipCutEntity houseEntity = optionalPainHouse.get();

        entity.setWorkflowShipCutEntity(houseEntity);
        // 动态计算子
        calcChild(entity);

        WorkflowShipCutChildEntity save = workflowShipCutChildDao.save(entity);

        return AjaxResult.success(save);
    }

    @PutMapping("/child/{id}")
    public AjaxResult updateChild(@PathVariable("id") Long id, @RequestBody WorkflowShipCutChildEntity entity) {

        entity.setId(id); // 新增保证 id = null，避免变成更新

        Optional<WorkflowShipCutEntity> optionalPainHouse = workflowShipCutDao.findById(entity.getPid());
        if(!optionalPainHouse.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_WORK_FLOW_MISSING);
        }

        WorkflowShipCutEntity houseEntity = optionalPainHouse.get();

        entity.setWorkflowShipCutEntity(houseEntity);
        // 动态计算子
        calcChild(entity);

        WorkflowShipCutChildEntity save = workflowShipCutChildDao.save(entity);

        save.setPid(houseEntity.getId());

        return AjaxResult.success(save);
    }

    @DeleteMapping("/child/{id}")
    public AjaxResult deleteChild(@PathVariable("id") Long id) {
        Optional<WorkflowShipCutChildEntity> childEntityOptional = workflowShipCutChildDao.findById(id);
        if(!childEntityOptional.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_CALIBRATION_MISSION);
        }

        WorkflowShipCutChildEntity childEntity = childEntityOptional.get();

        WorkflowShipCutEntity workflowPaintHouseEntity = childEntity.getWorkflowShipCutEntity();
        workflowPaintHouseEntity.getInner().remove(childEntity);

        workflowShipCutDao.save(workflowPaintHouseEntity);


        workflowShipCutChildDao.deleteById(id);

        return AjaxResult.success();
    }

    @Deprecated
//    @PostMapping("/child/sync")
    public AjaxResult syncChildPower(@RequestBody WorkflowPowerBody entity) {
        Date startTime = entity.getStartTime();
        Date endTime = entity.getEndTime();
        String mfid = entity.getMfid();
        Set<String> mfids = new HashSet<>();
        mfids.add(mfid);
        Map<String, HttpGetPowerReturnNewBody> powerMapByHourType = httpService2.getPowerListByHourType(mfids, startTime, endTime);

        HttpGetPowerReturnNewBody body = powerMapByHourType.get(mfid);
        Double power = 0.;
        if(ObjectUtils.isNotEmpty(body)) {
            power = body.getSum();
        }

        return AjaxResult.success(power);
    }


    @GetMapping("/child/sync/{id}")
    public AjaxResult syncChildPower(@PathVariable("id") Long id) {
        Optional<WorkflowShipCutChildEntity> optional = workflowShipCutChildDao.findById(id);
        if(!optional.isPresent()) {
            throw new ServiceException(MessageConstant.ERR_SYNC_WORKFLOW_MISSION);
        }
        WorkflowShipCutChildEntity entity = optional.get();
        Date startTime = entity.getStartTime();
        Date endTime = entity.getEndTime();
        String deviceNo = entity.getDeviceNo();
        String mfid = entity.getMfid();
        Set<String> mfids = new HashSet<>();
        mfids.add(mfid);
        Map<String, HttpGetPowerReturnNewBody> powerMapByHourType = httpService2.getPowerListByHourType(mfids, startTime, endTime);

        HttpGetPowerReturnNewBody body = powerMapByHourType.get(mfid);
        double power = 0.;
        if(ObjectUtils.isNotEmpty(body)) {
            power = body.getSum();
        }

        entity.setTotalPower(power);

        WorkflowShipCutChildEntity save = workflowShipCutChildDao.save(entity);

        return AjaxResult.success(save);

    }

    /////////////////////////////////////////////////  动态计算

    /**
     * 计算动态值
     * /**
     * 计算动态值
     *    shipName;        // 船体名称
     *    reporter;        // 填报人
     *    powers;          // 使用电量     //  子表求和
     *    powersByUnit;    // 单位用电量    //  power / weight
     *    shipPowers;      // 单船下料用电量  // power / weight * shipWeight
     *    o2ByUnit;        // 单位耗氧气量标定值        // CalibrationService.calcShipCut()  单位耗氧
     *    o2;              // 氧气量                  // shipWeight * o2ByUnit
     *    airByUnit;       // 单位耗压缩空气量标定值      // CalibrationService.calcShipCut()  单位耗气
     *    air;             // 压缩空气量                // shipWeight * airByUnit
     * @param entity
     * @param shipEntity
     * @param shipRepairEntity
     */

    public static WorkflowShipCutEntity dynamicCalc(WorkflowShipCutEntity entity,
                                                 ShipEntity shipEntity,
                                                 ShipRepairEntity shipRepairEntity,
                                                 CalibrationShipCutDto calibrationShipCutDto) {

        // 总电量， 子表求和
        List<WorkflowShipCutChildEntity> inner = entity.getInner();
        double sum = inner.stream().mapToDouble(t->t.getTotalPower() == null ? 0. : t.getTotalPower()).sum();

        inner.forEach(t->t.setPid(entity.getId()));

        entity.setPowers(sum);
        //////////////////////////////////////////////////
        Double powerByUnit = entity.getPowers() / entity.getWeight();
        entity.setPowersByUnit(powerByUnit);

        Double shipPowers = entity.getPowers() / entity.getWeight() * entity.getShipWeight();
        entity.setShipPowers(shipPowers);

        Double o2ByUnit = 0.;
        if(!ObjectUtils.isEmpty(calibrationShipCutDto)) {
            o2ByUnit = calibrationShipCutDto.o2Unit;
        }
        entity.setO2ByUnit(o2ByUnit);

        Double o2 = entity.getShipWeight() * o2ByUnit;
        entity.setO2(o2);

        entity.setAirByUnit(0.);
        entity.setAir(0.);

        ///////////////////////////////////////////////////
        entity.setShipName(shipEntity.getName());
        entity.setReporter(shipRepairEntity.getUpdater());
        entity.setShipRepairId(shipRepairEntity.getId());
        return entity;
    }

    private WorkflowShipCutChildEntity calcChild(WorkflowShipCutChildEntity entity) {
        // TODO 发送请求，获取数据
        // Double totalPower = xxx
        // entity.setTotalPower(totalPower)
        // 此处暂时写死
//        entity.setTotalPower(0.);

        return entity;
    }
}
